home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
cmln0585.arc
/
BSLP.DOC
< prev
next >
Wrap
Text File
|
1986-02-27
|
67KB
|
2,228 lines
BSLP BASIC
INTRODUCTION
BMLP and BSLP are preprocessor tools for Microsoft BASIC.
BMLP is a macro language preprocessor. It allows you to write
your programs using macros which you define in the program or
within macro library text files.
BSLP takes a source file containing special structured
statements and translates it into a program containing BASIC
statements.
Using these tools will help you write more concise, better
structured BASIC programs, by allowing you to take advantage
of these features:
- program with macros using parameters and subroutines that
are maintained in libraries where they can be accessed by
all your programs.
- write free-form, indented statements without line numbers.
- include statements from many separate files and libraries
into a single BASIC program. (This lets you write and
maintain your programs in small modules.)
- organize your subroutines into procedures, each with its
own descriptive alpha-numeric name.
- structure your programming with multi-line conditionals,
loop and case constructs similar to those found in
programming languages like C and Pascal.
When using these preprocessors, please bear in mind that
these versions are written in BASIC and are provided for your
use and you are free to modify them in any manner you see fit.
If you find these tools useful, we have a package called PPE
(Professional Programming Environment) that includes a super
preprocessor (SLPC) which is written in C for faster
processing (300-400 lines/min). It does everything that
these do PLUS a lot more, like providing a define statement
for text substitution and built-in random file handling macro
statements. It comes with a large library of macros and a
library manager program.
If you have suggestions, questions, comments or would like
more information about the PPE package,
please contact us at:
Bendorf Associates
P.O. Box 5910è 6006 S. Main
Roswell, NM 88201
(505) 347-5701
The following is a list and brief abstract of the files on
this disk:
Files for BSLP: Basic Structured Language Preprocessor
BSLP.P . . . . . . . Structured Language Source Text
BSLP.BAS . . . . . . Microsoft Basic Source Code
BSLP.DOC . . . . . . Documentation
BSLP.MSD . . . . . . MS-DOS Compiled Version (.EXE)
BSLP.CPM . . . . . . CP/M 80 Compiled Version (.COM)
Files for BMLP: Basic Macro Language Preprocessor
BMLP.P . . . . . . . Structured Language Source Text
BMLP.BAS . . . . . . Microsoft Basic Source Code
BMLP.DOC . . . . . . Documentation
BMLP.MSD . . . . . . MS-DOS Compiled Version (.EXE)
BMLP.CPM . . . . . . CP/M 80 Compiled Version (.COM)
Files for BSLP & BMLP example programs
XFRAME.M . . . . . . Example Program Source Text
XFRAME.ML . . . . . Library for XFRAME.M
BINPUT.M . . . . . . Example Program Source Text
BINPUT.ML . . . . . Library for BINPUT.M
BSLP.BAS
100 DATA proc...
101 DATA prog...
102 DATA when...
103 DATA unless.
104 DATA repeat.
105 DATA loop...
106 DATA switch.
107 DATA case...
108 DATA else...
109 DATA break..
110 DATA endp...
111 DATA pend...
112 DATA endw...
113 DATA endu...
114 DATA until..
115 DATA endl...
116 DATA endc...
117 PROC.% = 1
118 PROG.% = 2
119 WHEN.% = 3
120 UNLESS.% = 4
121 REPEAT.% = 5è122 LOOP.% = 6
123 SWITCH.% = 7
124 CASE.% = 8
125 ELSE.% = 9
126 BREAK.% = 10
127 ENDP.% = 11
128 PEND.% = 12
129 ENDW.% = 13
130 ENDU.% = 14
131 UNTIL.% = 15
132 ENDL.% = 16
133 ENDC.% = 17
134 DATA 11,12,13,14,15,16,17,17,13,17
135 DOT$ = "."
136 DOTS$ = "...."
137 SKIP$ = " "
138 SKIP1$ = " '"
139 OEXT$ = ".BAS"
140 IEXT$ = ".P"
141 EEXT$ = ".E"
142 INCL$ = ".INC"
143 TM$ = " ,="
144 T.FILE$ = "BSLP.$$$"
145 T.FILE% = 1
146 E.FILE% = 2
147 I.FILE% = 3
148 O.FILE% = 3
149 ERRORS% = 0
150 KERR% = 1
151 LEVELS% = 0
152 PUSH% = 0
153 NUM% = 0
154 STACK.% = 0
155 NKEY% = 17
156 INCS% = 1
157 INC% = 0
158 FILE% = 2
159 BASIC$ = "restore.resume.return.goto.gosub"
160 DIM CLOSING%(10) ' For error messages.
161 DIM INC$(50) ' Include file stack.
162 DIM STACK$(500)
163 DIM STACK%(500)
164 DIM NUM.%(500)
165 DIM KEYWORD.%(99,2)
166 DIM XN.%(99)
167 DIM LOOPS%(99)
168 DIM SWITCH$(10) ' For the left operand of SWITCH.
169 DIM KEYWORD$(22) ' For error messages.
170 FOR I%=1 TO NKEY%:READ BUF$:TABLE$=TABLE$+BUF$:KEYWORD$(I%)=BUF$:NEXT I%
171 FOR I%=1 TO 10:READ CLOSING%(I%):NEXT I%
172 PRINT "BSLP V1.1B (C) BENDORF ASSOCIATES, 1984-85"
173 PRINT:GoSub 566
174 IF NOT(GOOD%) GOTO 177
175 GoSub 181
176 GOTO 179è177 IF NOT(I.FILE$<>"") GOTO 179
178 PRINT"CANNOT OPEN ";I.FILE$
179 END
180 'BEGIN
181 GoSub 194
182 CLOSE
183 IF NOT(ERRORS%=0) GOTO 186
184 KILL E.FILE$:GoSub 463:CLOSE:KILL T.FILE$
185 GOTO 188
186 KILL T.FILE$:PRINT E.FILE$;" PRODUCED WITH ";STR$(ERRORS%);" ERROR(S)."
187 END
188 IF NOT(ERRORS%>0) GOTO 191
189 KILL O.FILE$:PRINT O.FILE$;" ABORTED WITH ";STR$(ERRORS%);" ERROR(S)."
190 GOTO 192
191 PRINT"<";O.FILE$;"> DONE!"
192 RETURN
193 'PASS_1
194 Open"O",T.FILE%,T.FILE$:Open"O",E.FILE%,E.FILE$:GoSub 290:INC$(INCS%)=I.FILE$
195 INC%=INC%+1:FILE%=FILE%+1:FILE$=INC$(INC%):Open"I",FILE%,FILE$
196 GoSub 201:GoSub 275
197 IF NOT(FILE%=2) GOTO 196
198 IF NOT(INC%=INCS%) GOTO 195
199 RETURN
200 'INPUT-SOURCE
201 LINE INPUT #FILE%,BUF$
202 IF NOT(LEN(BUF$)>2) GOTO 226
203 XLINE$=BUF$:GoSub 232
204 IF(LEN(BUF$)=0) GOTO 225
205 INDEX%=0:GoSub 550
206 IF NOT(RIGHT$(TEXT$,1)=":") GOTO 210
207 IF(LEN(SBUFF$)>0)THEN GoSub 266
208 FLAG%=2:LEVEL$=LEFT$(TEXT$,LEN(TEXT$)-1):COMMENT$=SKIP1$+LEVEL$:GoSub 435
209 GOTO 225
210 L$=LEFT$(TEXT$,1):KEYWORD%=0
211 IF(LEN(TEXT$)<4 OR LEN(TEXT$)>6) GOTO 213
212 C.$=TEXT$:GoSub 606:KEYS$=C.$+DOTS$:KEYWORD%=INSTR(1,TABLE$,LEFT$(KEYS$,7)):KEYWORD%=(KEYWORD%+6)\7
213 IF NOT(KEYWORD%>0) GOTO 217
214 IF(LEN(SBUFF$)>0)THEN GoSub 266
215 GoSub 269
216 GOTO 225
217 IF NOT(L$="-") GOTO 220
218 GoSub 588
219 GOTO 225
220 IF NOT(L$="+") GOTO 224
221 IF(LEN(SBUFF$)>0)THEN GoSub 266
222 GoSub 581
223 GOTO 225
224 GoSub 251
225 NERR%=NERR%+1:PRINT #E.FILE%,STR$(NERR%);SKIP$;XLINE$
226 IF NOT(EOF(FILE%)) GOTO 201
227 CLOSE #FILE%:FILE%=FILE%-1
228 IF(SBUFF$="") GOTO 230
229 BUF$="":CFLAG%=0:GoSub 251
230 RETURN
231 'STRIPè232 Z1%=INSTR(BUF$,CHR$(9)):Z2%=INSTR(BUF$,CHR$(10))
233 WHILE (Z1% OR Z2%)
234 IF Z1% THEN MID$(BUF$,Z1%,1)=" "
235 IF Z2% THEN MID$(BUF$,Z2%,1)=" "
236 Z1%=INSTR(BUF$,CHR$(9)):Z2%=INSTR(BUF$,CHR$(10)):WEND
237 Z1%=1:WHILE (MID$(BUF$,Z1%,1)=" " AND Z1%<LEN(BUF$)):Z1%=Z1%+1:WEND
238 Z2%=LEN(BUF$):WHILE (MID$(BUF$,Z2%,1)=" " AND Z2%>1):Z2%=Z2%-1:WEND
239 IF NOT(Z2%<Z1%) GOTO 242
240 BUF$=""
241 GOTO 245
242 BUF$=MID$(BUF$,Z1%,Z2%-Z1%+1)
243 IF NOT(LEN(BUF$)>0) GOTO 245
244 IF(LEFT$(BUF$,1)="'" OR LEFT$(BUF$,3)="REM" OR BUF$=STRING$(LEN(BUF$),32))THEN BUF$=""
245 LN.%=LEN(BUF$):CFLAG%=0
246 IF(LN.%=0) GOTO 249
247 CFLAG%=(RIGHT$(BUF$,1)="|")
248 IF(CFLAG%)THEN BUF$=LEFT$(BUF$,LN.%-1):LN.%=LEN(BUF$)
249 RETURN
250 'OUT_PUT
251 IF NOT(CFLAG%=0) GOTO 259
252 IF NOT(LEN(SBUFF$)>0) GOTO 257
253 IF NOT(LEN(SBUFF$+BUF$)<=250) GOTO 256
254 BUF$=SBUFF$+BUF$:SBUFF$=""
255 GOTO 257
256 GoSub 266
257 PBUF$=BUF$:FLAG%=3:GoSub 435
258 GOTO 263
259 IF NOT(LEN(SBUFF$+BUF$)<=250) GOTO 262
260 SBUFF$=SBUFF$+BUF$+":"
261 GOTO 263
262 GoSub 266:PBUF$=BUF$:GoSub 435
263 BUF$=""
264 RETURN
265 'DUMP
266 PBUF$=LEFT$(SBUFF$,LEN(SBUFF$)-1):FLAG%=3:GoSub 435:SBUFF$="":CFLAG%=0
267 RETURN
268 'KEYWORDS
269 KERR%=NERR%+1
270 ON KEYWORD% GOTO 302,319,328,354,364,364
271 ON KEYWORD%-6 GOTO 405,411,331,421,309,322,343
272 ON KEYWORD%-13 GOTO 357,371,381,428
273 RETURN
274 'POP_ERRORS
275 KER%=KERR%:KWDS%=KEYWORD%:GoSub 293
276 while KEYWORD%>0
277 GoSub 282
278 wend
279 GoSub 290:KEYWORD%=KWDS%:KERR%=KER%
280 RETURN
281 'RESOLVE-ERRORS
282 IF(KEYWORD%<11)THEN KEYWORD%=CLOSING%(KEYWORD%)
283 EBUF$=KEYWORD$(KEYWORD%):GoSub 603
284 IF NOT(KEYWORD%=ENDW.% OR KEYWORD%=ENDU.% OR KEYWORD%=ENDC.%) GOTO 287
285 IF(KEYWORD%=ENDC.%)THEN GoSub 293
286 GoSub 293è287 GoSub 293
288 RETURN
289 'PUSH
290 PUSH%=PUSH%+1:KEYWORD.%(PUSH%,0)=KEYWORD%:KEYWORD.%(PUSH%,1)=KERR%:KEYWORD.%(PUSH%,2)=LEVEL%
291 RETURN
292 'POP
293 IF NOT(PUSH%>0) GOTO 296
294 KEYWORD%=KEYWORD.%(PUSH%,0):KERR%=KEYWORD.%(PUSH%,1):LEVEL%=KEYWORD.%(PUSH%,2):PUSH%=PUSH%-1
295 GOTO 297
296 LEVEL%=-1:KEYWORD%=-1
297 RETURN
298 'LEVEL
299 LEVELS%=LEVELS%+1:LEVEL%=LEVELS%:TK%=LEVEL%:GoSub 290
300 RETURN
301 '_PROC
302 GoSub 275:GoSub 290:GoSub 550
303 IF NOT(LEN(TEXT$)>0) GOTO 306
304 COMMENT$=SKIP1$+TEXT$:LPROC$=TEXT$:FLAG%=2:LEVEL$=TEXT$:GoSub 435
305 GOTO 307
306 EBUF$="procedure name":GoSub 603
307 RETURN
308 '_ENDP
309 GoSub 293
310 WHILE KEYWORD%<>PROC.% AND KEYWORD%>0
311 GoSub 282
312 WEND
313 IF NOT(KEYWORD%=PROC.%) GOTO 316
314 FLAG%=3:PBUF$="RETURN":GoSub 435
315 GOTO 317
316 EBUF$=KEYWORD$(PROC.%):GoSub 603
317 RETURN
318 '_PROG
319 PROG..%=1
320 RETURN
321 '_PEND
322 IF NOT(PROG..%=1) GOTO 325
323 FLAG%=3:PBUF$="END":GoSub 435
324 GOTO 326
325 EBUF$=KEYWORD$(PROG.%):GoSub 603
326 RETURN
327 '_WHEN
328 GoSub 299:GoSub 299:FLAG%=1:GoSub 435
329 RETURN
330 '_ELSE
331 GoSub 293
332 IF NOT(KEYWORD%=WHEN.%) GOTO 340
333 F.%=LEVEL%:GoSub 293:T.%=LEVEL%:TK%=T.%:FLAG%=4:PBUF$="GOTO ":GoSub 435:XN%=XN%+1:XN.%(XN%)=F.%:GoSub 550:C.$=TEXT$:GoSub 606
334 IF NOT(C.$="when" OR C.$="unless") GOTO 337
335 GoSub 299:F.%=LEVEL%:FLAG%=ABS(C.$="when"):GoSub 435:GoSub 293
336 GOTO 338
337 F.%=0
338 KEYWORD%=WHEN.%:LEVEL%=T.%:GoSub 290:LEVEL%=F.%:GoSub 290
339 GOTO 341
340 GoSub 290:EBUF$=KEYWORD$(WHEN.%):GoSub 603
341 RETURNè342 '_ENDW
343 GoSub 293
344 IF NOT(KEYWORD%=WHEN.%) GOTO 347
345 F.%=LEVEL%:GoSub 293:T.%=LEVEL%:GoSub 350
346 GOTO 348
347 GoSub 290:EBUF$=KEYWORD$(WHEN.%):GoSub 603
348 RETURN
349 'POPOFF
350 IF(F.%>0)THEN XN%=XN%+1:XN.%(XN%)=F.%
351 IF(T.%>0)THEN XN%=XN%+1:XN.%(XN%)=T.%
352 RETURN
353 '_UNLESS
354 GoSub 299:GoSub 299:FLAG%=0:GoSub 435
355 RETURN
356 '_ENDU
357 GoSub 293
358 IF NOT(KEYWORD%=UNLESS.%) GOTO 361
359 F.%=LEVEL%:GoSub 293:T.%=LEVEL%:GoSub 350
360 GOTO 362
361 GoSub 290:EBUF$=KEYWORD$(UNLESS.%):GoSub 603
362 RETURN
363 '_REPEAT
364 GoSub 550:C.$=TEXT$:GoSub 606:LOOP%=LOOP%+1:GoSub 299:XN%=XN%+1:XN.%(XN%)=LEVEL%
365 IF NOT(C.$<>"when" AND C.$<>"unless") GOTO 368
366 LOOPS%(LOOP%)=LEVEL%
367 GOTO 369
368 LOOPS%(LOOP%)=LEVEL%*-1:GoSub 293:LEVEL%=LEVEL%*-1:GoSub 290:GoSub 299:FLAG%=ABS(C.$="when"):GoSub 435
369 RETURN
370 '_UNTIL
371 IF NOT(LOOP%>0) GOTO 378
372 GoSub 293
373 IF NOT(KEYWORD%=REPEAT.% OR KEYWORD%=LOOP.%) GOTO 376
374 LOOP%=LOOP%-1:TK%=LOOPS%(LOOP%+1):FLAG%=1:GoSub 435
375 GOTO 377
376 GoSub 290:EBUF$=KEYWORD$(REPEAT.%):GoSub 603
377 GOTO 379
378 EBUF$=KEYWORD$(REPEAT.%):GoSub 603
379 RETURN
380 '_ENDL
381 IF NOT(LOOP%>0) GOTO 402
382 GoSub 293
383 IF NOT(KEYWORD%=REPEAT.% OR KEYWORD%=LOOP.%) GOTO 400
384 GoSub 550:C.$=TEXT$:GoSub 606:LOOP%=LOOP%-1
385 IF NOT(LOOPS%(LOOP%+1)>0) GOTO 392
386 TK%=LOOPS%(LOOP%+1)
387 IF NOT(C.$="when" OR C.$="unless") GOTO 390
388 FLAG%=ABS(C.$="when"):GoSub 435
389 GOTO 391
390 EBUF$=KEYWORD$(WHEN.%):GoSub 603
391 GOTO 399
392 TK%=LOOPS%(LOOP%+1)*-1
393 IF NOT(C.$="when" OR C.$="unless") GOTO 396
394 FLAG%=ABS(C.$="when")
395 GOTO 397
396 FLAG%=4:PBUF$="GOTO "è397 GoSub 435
398 F.%=LEVEL%:GoSub 293:T.%=LEVEL%:GoSub 350
399 GOTO 401
400 GoSub 290:EBUF$=KEYWORD$(LOOP.%):GoSub 603
401 GOTO 403
402 EBUF$=KEYWORD$(LOOP.%):GoSub 603
403 RETURN
404 '_SWITCH
405 IF NOT(C.LN.%>0) GOTO 408
406 GoSub 299:GoSub 299:GoSub 299:SWITCH$(SWITCH%+1)=COND$:SWITCH%=SWITCH%+1
407 GOTO 409
408 EBUF$="operand":GoSub 603
409 RETURN
410 '_CASE
411 GoSub 293
412 IF NOT(KEYWORD%=SWITCH.% AND SWITCH%>0) GOTO 418
413 IF NOT(C.LN.%>0) GOTO 416
414 XN%=XN%+1:XN.%(XN%)=LEVEL%:GoSub 299:FLAG%=4:PBUF$="IF("+SWITCH$(SWITCH%)+"<>"+COND$+") GOTO ":GoSub 435
415 GOTO 417
416 EBUF$="operand":GoSub 603
417 GOTO 419
418 GoSub 290:EBUF$=KEYWORD$(SWITCH.%):GoSub 603
419 RETURN
420 '_BREAK
421 GoSub 293
422 IF NOT(KEYWORD%=SWITCH.%) GOTO 425
423 F.%=LEVEL%:GoSub 293:T.%=LEVEL%:TK%=T.%:FLAG%=4:PBUF$="GOTO ":GoSub 435:KEYWORD%=SWITCH.%:LEVEL%=T.%:GoSub 290:LEVEL%=F.%:GoSub 290
424 GOTO 426
425 GoSub 290:EBUF$=KEYWORD$(SWITCH.%):GoSub 603
426 RETURN
427 '_ENDC
428 GoSub 293
429 IF NOT(KEYWORD%=SWITCH.%) GOTO 432
430 F.%=LEVEL%:GoSub 293:T.%=LEVEL%:GoSub 293:GoSub 350:SWITCH%=SWITCH%-1
431 GOTO 433
432 GoSub 290:EBUF$=KEYWORD$(SWITCH.%):GoSub 603
433 RETURN
434 'OUT_LINE
435 IF NOT(FLAG%<2 AND C.LN.%=0) GOTO 438
436 EBUF$="condition":GoSub 603
437 GOTO 453
438 NUM%=NUM%+1:OFFSET%=1
439 IF(FLAG%<2 OR FLAG%>3)THEN LEVEL$=STR$(TK%):MID$(LEVEL$,1,1)="@"
440 IF(FLAG%<>0) GOTO 443
441 PBUF$="IF("+COND$+") GOTO "+LEVEL$
442 GOTO 451
443 IF(FLAG%<>1) GOTO 446
444 PBUF$="IF NOT("+COND$+") GOTO "+LEVEL$
445 GOTO 451
446 IF(FLAG%<>2) GOTO 449
447 GoSub 459
448 GOTO 451
449 IF(FLAG%<>4) GOTO 451
450 PBUF$=PBUF$+LEVEL$
451 PRINT #T.FILE%,RIGHT$(STR$(NUM%),LEN(STR$(NUM%))-1);SKIP$;PBUF$;COMMENT$è452 IF(XN%>0 AND FLAG%<>2)THEN GoSub 456
453 COMMENT$="":PBUF$="":LEVEL$=""
454 RETURN
455 'STORE_IT
456 OFFSET%=0:FOR I%=1 TO XN%:LEVEL$=STR$(XN.%(I%)):MID$(LEVEL$,1,1)="@":GoSub 459:NEXT I%:XN%=0
457 RETURN
458 'STACK_IT
459 STACK.%=STACK.%+1:STACK%(STACK.%)=NUM%+OFFSET%:STACK$(STACK.%)=LEVEL$:IF(COMPIL%)THEN NUM.%(STACK.%)=NUM%+OFFSET%
460 OFFSET%=0
461 RETURN
462 'PASS_2
463 GoSub 534:OFFSET%=2:Open"I",T.FILE%,T.FILE$:Open"O",O.FILE%,O.FILE$
464 LINE INPUT #T.FILE%,BUF$:GoSub 468
465 IF NOT(EOF(T.FILE%)) GOTO 464
466 RETURN
467 'PROCESS_1
468 INDEX%=0:ONFLAG%=0:LN.%=LEN(BUF$):GoSub 550:IF(COMPIL%)THEN GoSub 477
469 while FIRST%<=LEN(BUF$)
470 IF(LEN(TEXT$)>7 OR LEN(TEXT$)<2 OR VAL(TEXT$)>0) GOTO 472
471 GoSub 491
472 GoSub 550
473 wend
474 PRINT #O.FILE%,BUF$
475 RETURN
476 'COMPIL
477 TEXT%=VAL(TEXT$):HIGH%=STACK.%+1:LOW%=0
478 IF(TEXT%<NUM.%(1) OR TEXT%>NUM.%(STACK.%)) GOTO 488
479 while((HIGH%-LOW%)>1):I%=(HIGH%+LOW%)\2
480 IF NOT(NUM.%(I%)=TEXT%) GOTO 483
481 TEXT%=-1:LOW%=HIGH%
482 GOTO 487
483 IF NOT(NUM.%(I%)<TEXT%) GOTO 486
484 LOW%=I%
485 GOTO 487
486 HIGH%=I%
487 wend
488 IF(TEXT%>0)THEN BUF$=SPACE$(LEN(TEXT$)+1)+COND$
489 RETURN
490 'FIND_IT
491 C.$=TEXT$:GoSub 606
492 IF NOT(C.$="on") GOTO 495
493 ONFLAG%=-1
494 GOTO 502
495 IF NOT(LEN(C.$)>3) GOTO 502
496 IF(INSTR(BASIC$,C.$)=0 OR COLN%) GOTO 502
497 GoSub 550:I$=LEFT$(TEXT$,1)
498 IF(I$="@" OR LEN(TEXT$)<>4) GOTO 500
499 C.$=TEXT$:GoSub 606:IF(C.$="else")THEN RETURN
500 IF(I$="0" AND ONFLAG%) GOTO 502
501 IF(ONFLAG%)THEN GoSub 504 ELSE GoSub 512
502 RETURN
503 'ON_FLAG
504 OFFSET%=1
505 while(FIRST%<=LEN(BUF$))
506 IF(TEXT$<>"")THEN GoSub 512è507 GoSub 550
508 wend
509 OFFSET%=2
510 RETURN
511 'SEARCH
512 HIGH%=STACK.%+1:LOW%=0:FIND%=-1
513 while((HIGH%-LOW%)>1):I%=(HIGH%+LOW%)\2
514 IF NOT(STACK$(I%)=TEXT$) GOTO 517
515 FIND%=STACK%(I%):LOW%=HIGH%
516 GOTO 521
517 IF NOT(STACK$(I%)<TEXT$) GOTO 520
518 LOW%=I%
519 GOTO 521
520 HIGH%=I%
521 wend
522 IF NOT(FIND%>0) GOTO 525
523 GoSub 529
524 GOTO 527
525 IF NOT(TEXT$<>"") GOTO 527
526 ERRORS%=ERRORS%+1:PRINT"MISSING LABEL (";TEXT$;")"
527 RETURN
528 'STUFF_IT
529 NUM$=STR$(FIND%):SP$="":L$=LEFT$(BUF$,FIRST%-OFFSET%)
530 IF(LEFT$(COND$,1)<>" " AND LEFT$(COND$,1)<>":" AND ONFLAG%=0)THEN SP$=" "
531 BUF$=L$+NUM$+SP$+COND$:INDEX%=LEN(L$)+LEN(NUM$):LN.%=LEN(BUF$)
532 RETURN
533 'SORT
534 PT.%=STACK.%:while (PT.%>0):PT.%=PT.%\2
535 IF NOT(PT.%>0) GOTO 547
536 JT.%=1:KT.%=STACK.%-PT.%:while (JT.%<=KT.%):LT.%=JT.%:CT.%=LT.%+PT.%
537 while (LT.%>0 AND STACK$(LT.%)>=STACK$(CT.%))
538 SWAP STACK$(LT.%),STACK$(CT.%):SWAP STACK%(LT.%),STACK%(CT.%)
539 CT.%=LT.%:LT.%=LT.%-PT.%:LT.%=LT.%*(1+(LT.%<0))
540 wend
541 IF NOT(COMPIL%) GOTO 546
542 LT.%=JT.%:CT.%=LT.%+PT.%
543 while (LT.%>0 AND NUM.%(LT.%)>=NUM.%(CT.%))
544 SWAP NUM.%(LT.%),NUM.%(CT.%):CT.%=LT.%:LT.%=LT.%-PT.%:LT.%=LT.%*(1+(LT.%<0))
545 wend
546 JT.%=JT.%+1:wend
547 wend
548 RETURN
549 'PARSER
550 C.LN.%=0:I.%=0:COLN%=0:II%=32:TEXT%=0:COND$="":TRM$=TM$+CHR$(58*ABS(INDEX%>0))
551 while(INSTR(TRM$,CHR$(II%))>0):INDEX%=INDEX%+1:IF(INDEX%<=LEN(BUF$))THEN II%=ASC(MID$(BUF$,INDEX%,1)) ELSE II%=7
552 wend:FIRST%=INDEX%
553 while(II%<>32 AND II%<>7)
554 IF NOT(INSTR(TRM$,CHR$(II%))>0 AND TEXT%=0) GOTO 557
555 COLN%=(CHR$(II%)=":"):I.%=1:II%=32
556 GOTO 562
557 IF NOT(II%=34 OR II%=40 OR II%=41) GOTO 560
558 IF(II%=34)THEN INDEX%=INSTR(INDEX%+1,BUF$,CHR$(34))
559 IF(II%=40)THEN TEXT%=TEXT%+1 ELSE IF(II%=41)THEN TEXT%=TEXT%-1
560 INDEX%=INDEX%+1:IF(INDEX%<=LEN(BUF$))THEN II%=ASC(MID$(BUF$,INDEX%,1)) ELSE II%=7
561 IF(II%=32 AND TEXT%<>0) GOTO 560è562 wend
563 TEXT$=MID$(BUF$,FIRST%,INDEX%-FIRST%):IF(LEN(BUF$)>INDEX%)THEN COND$=RIGHT$(BUF$,(LEN(BUF$)-INDEX%)+I.%):C.LN.%=LEN(COND$)
564 RETURN
565 'FILENAMES
566 LINE INPUT"INPUT FILE [.P]:",I.FILE$
567 IF(I.FILE$="") GOTO 579
568 COMPIL%=(INSTR(I.FILE$,"/")>0)
569 IF(COMPIL%)THEN I.FILE$=LEFT$(I.FILE$,LEN(I.FILE$)-1)
570 IF(INSTR(I.FILE$,DOT$)=0)THEN I.FILE$=I.FILE$+IEXT$
571 LK.$=I.FILE$:LK.%=I.FILE%:GoSub 614:I.FILE%=LK.%:GOOD%=(I.FILE%<>FALSE%)
572 IF(GOOD%=FALSE%) GOTO 579
573 I%=INSTR(1,I.FILE$,DOT$)
574 IF(I%=0)THEN I%=LEN(I.FILE$)+1
575 E.FILE$=LEFT$(I.FILE$,I%-1):LINE INPUT"OUTPUT FILE [.BAS]:",O.FILE$
576 IF(O.FILE$="")THEN O.FILE$=E.FILE$
577 IF(INSTR(O.FILE$,DOT$)=0)THEN O.FILE$=O.FILE$+OEXT$
578 IF(INSTR(E.FILE$,DOT$)=0)THEN E.FILE$=E.FILE$+EEXT$
579 RETURN
580 'INCLUDES
581 GoSub 599
582 IF NOT(FILE.%>0) GOTO 585
583 Open"I",FILE.%,FILE$:FILE%=FILE.%
584 GOTO 586
585 EBUF$="include "+FILE$:GoSub 603
586 RETURN
587 'SUBROUTINE
588 GoSub 599
589 IF NOT(FILE.%>0) GOTO 596
590 TEXT%=0
591 while(TEXT%<INCS%)
592 TEXT%=TEXT%+1:IF(FILE$=INC$(TEXT%))THEN TEXT%=INCS%+1
593 wend
594 IF(TEXT%=INCS%)THEN INCS%=INCS%+1:INC$(INCS%)=FILE$
595 GOTO 597
596 EBUF$="include "+FILE$:GoSub 603
597 RETURN
598 'FILES
599 FILE$=RIGHT$(TEXT$,LEN(TEXT$)-1):IF(INSTR(FILE$,DOT$)=0)THEN FILE$=FILE$+INCL$
600 FILE.%=FILE%+1:LK.$=FILE$:LK.%=FILE.%:GoSub 614:FILE.%=LK.%
601 RETURN
602 'ERRORS
603 ERRORS%=ERRORS%+1:EBUF$="ERR#"+STR$(ERRORS%)+" MISSING ("+EBUF$+") PROC <"+LPROC$+">":EBUF$=EBUF$+" AT"+STR$(KERR%):PRINT EBUF$:PRINT #E.FILE%,EBUF$
604 RETURN
605 '_Fold
606 f.0%=1
607 while(f.0%<=LEN(C.$))
608 f.2%=ASC(MID$(C.$,f.0%,1))
609 f.2%=f.2%+(32*ABS(f.2%>64 AND f.2%<91))
610 MID$(C.$,f.0%,1)=CHR$(f.2%):f.0%=f.0%+1
611 wend
612 RETURN
613 '_Lookup
614 OPEN"R",LK.%,LK.$:L.K!=LOF(LK.%):CLOSE LK.%
615 IF(L.K!<1)THEN LK.%=0:KILL LK.$
616 RETURNè
BSLP.DOC
BSLP Version 1.0B Page 1.0
Table of Contents
BSLP: Basic Structured Language Preprocessor......... 1.1
Functions...................................... 1.1
Invocation..................................... 1.1
Defaults....................................... 1.1
Option (/)..................................... 1.1
Structure Keywords............................. 1.1
PROG / PEND............................... 1.2
PROC / ENDP............................... 1.2
REPEAT / UNTIL............................ 1.3
LOOP / ENDL............................... 1.3
WHEN / ELSE / ENDW........................ 1.4
UNLESS / ENDU............................. 1.4
SWITCH / CASE / BREAK / ENDC.............. 1.5
Error Messages................................. 2.1
Structure Related Error Handling.......... 2.1
Structure Related Error Messages.......... 2.1
Included Files (+-)............................ 3.1
Notice:
Delimiter conventions used in this documentation
are:
<> denotes required information
[] denotes optional information
BSLP Version 1.0B Page 1.1
BSLP - Basic Structured Language Preprocessor
Function:
BSLP translates source text written in BSLP structure
language to standard BASIC code. BSLP is a BASIC language
version of the PPE structure translater. It is slow but very
usable, and has served well as a tool for prototype
extensions to the structure language. BSLP is written in BSLP
structure language and should be a useful learning tool.
Invocation:
Entering 'BSLP' at the DOS prompt will envoke the compiled
version (.EXE) of BSLP. The (.BAS) version will have to be
run using the interpreter by entering 'BASICA BSLP' at the
DOS prompt. BSLP will then prompt for the input file name and
the output file name. The default for the input file
extension is '.P', and the default for the output file
extension is '.BAS'. The slash (/) following the input file
name will cause all non-referenced line numbers to be deleted
from the output file (.BAS). This allows a smaller compiled
(.EXE) program.
Hints and Restrictions:
Structure keywords are not case or position sensitive, and
they must (except for spaces and tabs) be the first words on
a line. Do NOT use comments on the same line with keywords.
The vertical bar (|) may be use to provide line continuation.
Continued lines will be appended, separating them with a
colon (:).
Structure Keywords:
PROG / PEND
PROC <label> / ENDP
REPEAT / UNTIL <condition>
LOOP [<when/unless> <condition>] / ENDL [<when/unless> <condition>]
WHEN <condition> / ELSE [<when/unless> <condition>] / ENDW
è UNLESS <condition> / ENDU
SWITCH <left operand> / CASE <right operand> / BREAK / ENDC
BSLP - Basic Structured Language Preprocessor Page 1.1
BSLP Version 1.0B Page 1.2
Structure Keyword Definitions and Usage:
PROG / PEND
'PROG' identifies the main controlling procedure in a
program. 'PEND' identifies the end of the main procedure and
causes an "END" BASIC keyword to be generated.
Usage:
PROG Calculate <----------+
gosub process_one | Main
gosub process_two | Procedure
PEND <----------+
PROC <label> / ENDP
'PROC' defines the beginning of a procedure subroutine using
a label that may be referenced by name (e.g. 'GOSUB label')
from any other procedure in the same program. 'ENDP' closes
the matching 'PROC' and terminates the procedure with a
"RETURN" BASIC keyword. Procedures can not be nested.
Usage:
PROC Test_Out <----------+
when status = test | Subroutine
gosub test_it | Procedure
endw |
ENDP <----------+
*Note:
A label-name immediately followed by a colon (:) may be used
to identify a label without a procedure statement:
e.g... ERRORTRAP:
è
Structure Keyword Definitions and Usage Page 1.2
BSLP Version 1.0B Page 1.3
REPEAT / UNTIL <condition>
'REPEAT' defines the top of a conditional loop structure. The
matching 'UNTIL' defines the bottom of the loop where the
terminating condition is tested. The loop is terminated when
the condition evaluates true.
Usage:
REPEAT <----------+
index = index + 1 | Loop
gosub Index_task | Structure
UNTIL index = task.count <condition-+
LOOP [<when/unless> <condition>] / ENDL [<when/unless> <condition>]
'LOOP' defines the top of a loop structure that will allow a
condition to be tested at the top and or at the bottom
matching 'ENDL'. At the top 'WHEN' evaluates for a true
condition to continue into the loop structure, and 'UNLESS'
evaluates for a true condition to branch around the loop. At
the bottom 'WHEN' evaluates for a true condition to exit the
loop, and 'UNLESS' evaluates for a true condition to continue
the loop. One condition (top or bottom) is required, but both
may be use.
Usage:
LOOP <----------+
index = index + 1 | Loop
gosub Index_task | Structure
ENDL unless index < task <condition-+
LOOP when index < task <condition-+
index = index + 1 | Loop
gosub Index_task | Structure
ENDL <----------+
LOOP unless index >= task <condition-+
index = index + 1 | Loop
gosub Index_task | Structure
ENDL when index >= task <condition-+
è
Structure Keyword Definitions and Usage Page 1.3
BSLP Version 1.0B Page 1.4
WHEN <condition> / ELSE [<when/unless> <condition>] / ENDW
'WHEN-ELSE-ENDW' provides for multiple line conditional
constructs, with no limit on the range or depth of level and
no limit on the number of 'ELSE' statements used. 'ELSE WHEN'
defines the "ELSE-IF" construct, and 'ELSE UNLESS' defines
the "ELSE-IF-NOT" construct. 'ENDW' closes the matching
'WHEN' and terminates to the next outer level of processing.
Usage:
WHEN method = manual IF
goSub Keyboard THEN
ELSE WHEN method = auto ELSE IF
goSub Process THEN
ELSE UNLESS method = null ELSE IF NOT
goSub Process_End THEN
ELSE ELSE
goSub End_Process THEN
ENDW
UNLESS <condition> / ENDU
'UNLESS' defines a "DO WHEN NOT TRUE" construct and 'ENDU'
closes the matching 'UNLESS' and terminates to the next outer
level of processing.
Usage:
UNLESS abort = true IF NOT
gosub Continue THEN
ENDU
è
Structure Keyword Definitions and Usage Page 1.4
BSLP Version 1.0B Page 1.5
SWITCH <left operand> / CASE <right operand> / BREAK / ENDC
'SWITCH-CASE-ENDC' provides an "ON CONDITION PROCESS"
construct. 'SWITCH' defines the operand on the left side of
the equal sign and 'CASE' defines the operand on the right
side. There is no limit on the number of 'CASE' statements
within a procedure. When a 'SWITCH=CASE' is true, the
instructions following that 'CASE' are processed, and unless
a 'BREAK' statement is used, processing will continue through
to the next 'CASE' statement. The 'BREAK' statement will
cause a branch to the next 'ENDC' statement. The 'BREAK' will
be processed only if a 'SWITCH=CASE' is true. When a
'SWITCH=CASE' evaluates false, processing is branched to the
next 'CASE' statement. 'SWITCH' statements can be nested to
ten (10) levels. 'ENDC' closes the matching 'SWITCH' and
terminates to the next outer level of processing.
Usage:
SWITCH method$(method)
CASE "+"
answer = answer + number
BREAK
CASE "-"
answer = answer - number
BREAK
CASE "*"
answer = answer * number
BREAK
CASE "/"
when number <> 0
answer = answer / number
else
answer = 0
endw
ENDC
è
Structure Keyword Definitions and Usage Page 1.5
BSLP Version 1.0B Page 2.1
Structure Related Error Handling:
When a structure error is encountered, a file
(<program-name>.E) is generated, showing the exact location
of the error. All structure errors are resolved at the end of
each procedure, or 'ENDP'. When there are errors immediately
following an 'ENDP' statement, the procedure preceding the
'ENDP' statement will be the source of the errors.
Structure Related Error Messages:
Structure related error messages are displayed with a 'ERR#'
and the error count. These errors will be recorded in the
error file (<program-name>.E).
Structure related error messages are self explanatory, the
following are some typical examples:
ERR#1 MISSING (endl) PROC <BEGIN>
(A 'LOOP' structure not closed in procedure BEGIN)
ERR#1 MISSING (switch) PROC <Select>
(A 'CASE' or 'BREAK' or 'ENDC' without an opening
'SWITCH' in procedure Select.)
ERR#1 MISSING (endc) PROC <>
(A 'CASE' structure not closed in main procedure.)
ERR#1 MISSING (include 'filename')
(Unable to find an included file.)
è
Errors Page 2.1
BSLP Version 1.0B Page 3.1
Included Files:
There are two methods to include additional files into a
program source file for processing:
Immediate:
+filename.ext
The leading plus (+) will cause a file to be included
immediately into the program source file and processed. The
same file or any number of files may be included and
processed.
Stacked:
-filename.ext
The leading dash (-) will cause a file name to be stored and
the file will be included only one time at the end of the
main program source file. The same file name may be
referenced many times, with the file included into the
program source file only one time and processed. The internal
file name storage will hold up to fifty (50) file names.
*Note:
Nested includes may be processed up to five (5) levels deep.
Nesting is limited by the number of files that can be open at
the same time. No line numbered include files allowed.
WARNING:
A recursive include will blow the internal stack. No check is
made for recursive includes.
è
Including Files Page 3.1
BSLP.P
'------------------------------------------------------
'-(c) Bendorf Associates, 1984-85 -
'------------------------------------------------------
'- Program:BSLP (BASIC STRUCTURED LANGUAGE PREPROCESSOR)
'- System :PPE
'- Module :TOOLS
'- Task :COMPILE 'SSS' CODE INTO STANDARD BASIC CODE.
'- Created:10.1.82
'- By :D. L. BENDORF
'- Version:PUBLIC DOMAIN
'- Notes :THIS PROGRAM IS NOT FOR RESALE.
'- History:
'- BSLP translates source text written in 'SSS' structure language to
'- standard BASIC code. BSLP is a BASIC language version of the PPE
'- structure translater. It is slow but very usable, and has served well
'- as a tool for prototype extensions to the structure language. BSLP is
'- written in BSLP structure language and should be a useful learning
'- tool.
'- Invocation:
'- Entering 'BSLP' at the DOS prompt will envoke the compiled version
'- (.EXE) of BSLP. The (.BAS) version will have to be run using the
'- interpreter by entering 'BASICA BSLP' at the DOS prompt. BSLP will
'- then prompt for the input file name and the output file name. The
'- default for the input file extension is '.P', and the default for the
'- output file is 'input-file.BAS'. The slash (/) following the input
'- file name will cause all non-referenced line numbers to be deleted
'- from the output file (.BAS). This allows a smaller compiled (.EXE)
'- program.
'- Hints and Restrictions:
'- 'SSS' keywords are not case or position sensitive, and they must
'- (except for spaces and tabs) be the first words on a line. Do NOT use
'- comments on the same line with keywords. The vertical bar (|) may be
'- use to provide line continuation. Continued lines will be appended,
'- separating them with a colon (:).
'- 'SSS' Keywords:
'- PROG / PEND
'- PROC <label> / ENDP
'- REPEAT / UNTIL <condition>
'- LOOP [<when/unless> <condition>] / ENDL [<when/unless> <condition>]
'- WHEN <condition> / ELSE [<when/unless> <condition>] / ENDW
'- UNLESS <condition> / ENDU
'- SWITCH <left operand> / CASE <right operand> / BREAK / ENDC
'------------------------------------------------------
'- ** Data Division -
'------------------------------------------------------
DATA proc...
DATA prog...
DATA when...
DATA unless.
DATA repeat.èDATA loop...
DATA switch.
DATA case...
DATA else...
DATA break..
DATA endp...
DATA pend...
DATA endw...
DATA endu...
DATA until..
DATA endl...
DATA endc...
PROC.% = 1
PROG.% = 2
WHEN.% = 3
UNLESS.% = 4
REPEAT.% = 5
LOOP.% = 6
SWITCH.% = 7
CASE.% = 8
ELSE.% = 9
BREAK.% = 10
ENDP.% = 11
PEND.% = 12
ENDW.% = 13
ENDU.% = 14
UNTIL.% = 15
ENDL.% = 16
ENDC.% = 17
DATA 11,12,13,14,15,16,17,17,13,17
DOT$ = "."
DOTS$ = "...."
SKIP$ = " "
SKIP1$ = " '"
OEXT$ = ".BAS"
IEXT$ = ".P"
EEXT$ = ".E"
INCL$ = ".INC"
TM$ = " ,="
T.FILE$ = "BSLP.$$$"
T.FILE% = 1
E.FILE% = 2
I.FILE% = 3
O.FILE% = 3
ERRORS% = 0
KERR% = 1
LEVELS% = 0
PUSH% = 0
NUM% = 0
STACK.% = 0
NKEY% = 17
INCS% = 1
INC% = 0
FILE% = 2
BASIC$ = "restore.resume.return.goto.gosub"èDIM CLOSING%(10) ' For error messages.
DIM INC$(50) ' Include file stack.
DIM STACK$(500)
DIM STACK%(500)
DIM NUM.%(500)
DIM KEYWORD.%(99,2)
DIM XN.%(99)
DIM LOOPS%(99)
DIM SWITCH$(10) ' For the left operand of SWITCH.
DIM KEYWORD$(22) ' For error messages.
FOR I%=1 TO NKEY%|
READ BUF$|
TABLE$=TABLE$+BUF$|
KEYWORD$(I%)=BUF$|
NEXT I%
FOR I%=1 TO 10|
READ CLOSING%(I%)|
NEXT I%
'------------------------------------------------------
'- ** Procedure Division -
'------------------------------------------------------
prog BSLP
PRINT "BSLP V1.1B (C) BENDORF ASSOCIATES, 1984-85"
PRINT|
GoSub FILENAMES
when GOOD%
GoSub BEGIN
else when I.FILE$<>""
PRINT"CANNOT OPEN ";I.FILE$
endw
pend
proc BEGIN
GoSub PASS_1
'
' Kill the error file if no errors in PASS_1.
' Kill the temp file after PASS_2.
' Kill the output file if errors in PASS_2.
'
CLOSE
when ERRORS%=0
KILL E.FILE$|
GoSub PASS_2|
CLOSE|
KILL T.FILE$
else
KILL T.FILE$|
PRINT E.FILE$;" PRODUCED WITH ";STR$(ERRORS%);" ERROR(S)."
END
endw
when ERRORS%>0
KILL O.FILE$|
PRINT O.FILE$;" ABORTED WITH ";STR$(ERRORS%);" ERROR(S)."
else
PRINT"<";O.FILE$;"> DONE!"
endwèendp
proc PASS_1
'
' This is the first phase of processing.
' All included file will be processed here.
' The error file is written during this pass.
'
Open"O",T.FILE%,T.FILE$|
Open"O",E.FILE%,E.FILE$|
GoSub PUSH|
INC$(INCS%)=I.FILE$
loop
INC%=INC%+1|
FILE%=FILE%+1|
FILE$=INC$(INC%)|
Open"I",FILE%,FILE$
loop
GoSub INPUT-SOURCE|
GoSub POP_ERRORS
until FILE%=2
until INC%=INCS%
endp
proc INPUT-SOURCE
'
' Read the input file and look for SLP keywords.
' Look for include file operators(+-).
' Write error file just in case there is a PASS_1 error.
'
loop
LINE INPUT #FILE%,BUF$
when LEN(BUF$)>2
XLINE$=BUF$:GoSub STRIP
unless LEN(BUF$)=0
INDEX%=0:GoSub PARSER
when RIGHT$(TEXT$,1)=":"
IF(LEN(SBUFF$)>0)THEN GoSub DUMP
FLAG%=2:LEVEL$=LEFT$(TEXT$,LEN(TEXT$)-1)|
COMMENT$=SKIP1$+LEVEL$|
GoSub OUT_LINE
else
L$=LEFT$(TEXT$,1):KEYWORD%=0
unless LEN(TEXT$)<4 OR LEN(TEXT$)>6
C.$=TEXT$:GoSub _Fold|
KEYS$=C.$+DOTS$|
KEYWORD%=INSTR(1,TABLE$,LEFT$(KEYS$,7))|
KEYWORD%=(KEYWORD%+6)\7
endu
when KEYWORD%>0
IF(LEN(SBUFF$)>0)THEN GoSub DUMP
GoSub KEYWORDS
else when L$="-"
GoSub SUBROUTINE
else when L$="+"
IF(LEN(SBUFF$)>0)THEN GoSub DUMP
GoSub INCLUDESè else
GoSub OUT_PUT
endw
endw
endu
NERR%=NERR%+1|
PRINT #E.FILE%,STR$(NERR%);SKIP$;XLINE$
endw
until EOF(FILE%)
CLOSE #FILE%|
FILE%=FILE%-1
unless SBUFF$=""
BUF$="":CFLAG%=0:GoSub OUT_PUT
endu
endp
proc STRIP
'
' Strip the leading and trailing spaces,tabs and linefeeds off of
' the input buffer.
' Look for the continuation operator.
'
Z1%=INSTR(BUF$,CHR$(9)):Z2%=INSTR(BUF$,CHR$(10))
WHILE (Z1% OR Z2%)
IF Z1% THEN MID$(BUF$,Z1%,1)=" "
IF Z2% THEN MID$(BUF$,Z2%,1)=" "
Z1%=INSTR(BUF$,CHR$(9)):Z2%=INSTR(BUF$,CHR$(10))|
WEND
Z1%=1|
WHILE (MID$(BUF$,Z1%,1)=" " AND Z1%<LEN(BUF$))|
Z1%=Z1%+1|
WEND
Z2%=LEN(BUF$)|
WHILE (MID$(BUF$,Z2%,1)=" " AND Z2%>1)|
Z2%=Z2%-1|
WEND
when Z2%<Z1%
BUF$=""
else
BUF$=MID$(BUF$,Z1%,Z2%-Z1%+1)
when LEN(BUF$)>0
IF(LEFT$(BUF$,1)="'" OR LEFT$(BUF$,3)="REM" OR BUF$=STRING$(LEN(BUF$),32))THEN BUF$=""
endw
endw
LN.%=LEN(BUF$):CFLAG%=0
unless LN.%=0
CFLAG%=(RIGHT$(BUF$,1)="|")
IF(CFLAG%)THEN BUF$=LEFT$(BUF$,LN.%-1):LN.%=LEN(BUF$)
endu
endp
proc OUT_PUT
'
' Process lines not beginning with keywords.
' If CFLAG% flag is set, append input lines together
' and always check the total length first.
'è when CFLAG%=0
when LEN(SBUFF$)>0
when LEN(SBUFF$+BUF$)<=250
BUF$=SBUFF$+BUF$:SBUFF$=""
else
GoSub DUMP
endw
endw
PBUF$=BUF$:FLAG%=3:GoSub OUT_LINE
else when LEN(SBUFF$+BUF$)<=250
SBUFF$=SBUFF$+BUF$+":"
else
GoSub DUMP:PBUF$=BUF$:GoSub OUT_LINE
endw
BUF$=""
endp
proc DUMP
PBUF$=LEFT$(SBUFF$,LEN(SBUFF$)-1)|
FLAG%=3:GoSub OUT_LINE:SBUFF$="":CFLAG%=0
endp
proc KEYWORDS
'
' Branch to the right keyword processing.
' This is one of the few acceptable uses of the `GOTO'.
'
KERR%=NERR%+1
ON KEYWORD% GOTO _PROC,_PROG,_WHEN,_UNLESS,_REPEAT,_REPEAT
ON KEYWORD%-6 GOTO _SWITCH,_CASE,_ELSE,_BREAK,_ENDP,_PEND,_ENDW
ON KEYWORD%-13 GOTO _ENDU,_UNTIL,_ENDL,_ENDC
endp
proc POP_ERRORS
'
' Resolve all un-closed processes and report errors.
'
KER%=KERR%:KWDS%=KEYWORD%:GoSub POP
while KEYWORD%>0
GoSub RESOLVE-ERRORS
wend
GoSub PUSH:KEYWORD%=KWDS%:KERR%=KER%
endp
proc RESOLVE-ERRORS
IF(KEYWORD%<11)THEN KEYWORD%=CLOSING%(KEYWORD%)
EBUF$=KEYWORD$(KEYWORD%):GoSub ERRORS
when KEYWORD%=ENDW.% OR KEYWORD%=ENDU.% OR KEYWORD%=ENDC.%
IF(KEYWORD%=ENDC.%)THEN GoSub POP
GoSub POP
endw
GoSub POP
endp
proc PUSH
PUSH%=PUSH%+1|
KEYWORD.%(PUSH%,0)=KEYWORD%|
KEYWORD.%(PUSH%,1)=KERR%|
KEYWORD.%(PUSH%,2)=LEVEL%
endpèproc POP
when PUSH%>0
KEYWORD%=KEYWORD.%(PUSH%,0)|
KERR%=KEYWORD.%(PUSH%,1)|
LEVEL%=KEYWORD.%(PUSH%,2)|
PUSH%=PUSH%-1
else
LEVEL%=-1|
KEYWORD%=-1
endw
endp
proc LEVEL
LEVELS%=LEVELS%+1:LEVEL%=LEVELS%|
TK%=LEVEL%:GoSub PUSH
endp
proc _PROC
GoSub POP_ERRORS|
GoSub PUSH|
GoSub PARSER
when LEN(TEXT$)>0
COMMENT$=SKIP1$+TEXT$:LPROC$=TEXT$|
FLAG%=2:LEVEL$=TEXT$:GoSub OUT_LINE
else
EBUF$="procedure name":GoSub ERRORS
endw
endp
proc _ENDP
GoSub POP
WHILE KEYWORD%<>PROC.% AND KEYWORD%>0
GoSub RESOLVE-ERRORS
WEND
when KEYWORD%=PROC.%
FLAG%=3:PBUF$="RETURN":GoSub OUT_LINE
else
EBUF$=KEYWORD$(PROC.%):GoSub ERRORS
endw
endp
proc _PROG
PROG..%=1
endp
proc _PEND
when PROG..%=1
FLAG%=3:PBUF$="END":GoSub OUT_LINE
else
EBUF$=KEYWORD$(PROG.%):GoSub ERRORS
endw
endp
proc _WHEN
GoSub LEVEL:GoSub LEVEL|
FLAG%=1:GoSub OUT_LINE
endp
proc _ELSE
GoSub POP
when KEYWORD%=WHEN.%
F.%=LEVEL%:GoSub POP:T.%=LEVEL%:TK%=T.%|è FLAG%=4:PBUF$="GOTO ":GoSub OUT_LINE|
XN%=XN%+1:XN.%(XN%)=F.%|
GoSub PARSER:C.$=TEXT$:GoSub _Fold
when C.$="when" OR C.$="unless"
GoSub LEVEL:F.%=LEVEL%|
FLAG%=ABS(C.$="when"):GoSub OUT_LINE:GoSub POP
else
F.%=0
endw
KEYWORD%=WHEN.%|
LEVEL%=T.%:GoSub PUSH|
LEVEL%=F.%:GoSub PUSH
else
GoSub PUSH|
EBUF$=KEYWORD$(WHEN.%):GoSub ERRORS
endw
endp
proc _ENDW
GoSub POP
when KEYWORD%=WHEN.%
F.%=LEVEL%:GoSub POP:T.%=LEVEL%:GoSub POPOFF
else
GoSub PUSH|
EBUF$=KEYWORD$(WHEN.%):GoSub ERRORS
endw
endp
proc POPOFF
IF(F.%>0)THEN XN%=XN%+1:XN.%(XN%)=F.%
IF(T.%>0)THEN XN%=XN%+1:XN.%(XN%)=T.%
endp
proc _UNLESS
GoSub LEVEL:GoSub LEVEL|
FLAG%=0:GoSub OUT_LINE
endp
proc _ENDU
GoSub POP
when KEYWORD%=UNLESS.%
F.%=LEVEL%:GoSub POP:T.%=LEVEL%:GoSub POPOFF
else
GoSub PUSH|
EBUF$=KEYWORD$(UNLESS.%):GoSub ERRORS
endw
endp
proc _REPEAT
GoSub PARSER:C.$=TEXT$:GoSub _Fold|
LOOP%=LOOP%+1:GoSub LEVEL|
XN%=XN%+1:XN.%(XN%)=LEVEL%
when C.$<>"when" AND C.$<>"unless"
LOOPS%(LOOP%)=LEVEL%|
else
LOOPS%(LOOP%)=LEVEL%*-1|
GoSub POP:LEVEL%=LEVEL%*-1:GoSub PUSH|
GoSub LEVEL|
FLAG%=ABS(C.$="when")|
GoSub OUT_LINEè endw
endp
proc _UNTIL
when LOOP%>0
GoSub POP
when KEYWORD%=REPEAT.% OR KEYWORD%=LOOP.%
LOOP%=LOOP%-1:TK%=LOOPS%(LOOP%+1)|
FLAG%=1:GoSub OUT_LINE
else
GoSub PUSH|
EBUF$=KEYWORD$(REPEAT.%):GoSub ERRORS
endw
else
EBUF$=KEYWORD$(REPEAT.%):GoSub ERRORS
endw
endp
proc _ENDL
when LOOP%>0
GoSub POP
when KEYWORD%=REPEAT.% OR KEYWORD%=LOOP.%
GoSub PARSER:C.$=TEXT$:GoSub _Fold|
LOOP%=LOOP%-1
when LOOPS%(LOOP%+1)>0
TK%=LOOPS%(LOOP%+1)
when C.$="when" OR C.$="unless"
FLAG%=ABS(C.$="when"):GoSub OUT_LINE
else
EBUF$=KEYWORD$(WHEN.%):GoSub ERRORS
endw
else
TK%=LOOPS%(LOOP%+1)*-1
when C.$="when" OR C.$="unless"
FLAG%=ABS(C.$="when")
else
FLAG%=4:PBUF$="GOTO "
endw
GoSub OUT_LINE
F.%=LEVEL%:GoSub POP:T.%=LEVEL%:GoSub POPOFF
endw
else
GoSub PUSH|
EBUF$=KEYWORD$(LOOP.%):GoSub ERRORS
endw
else
EBUF$=KEYWORD$(LOOP.%):GoSub ERRORS
endw
endp
proc _SWITCH
when C.LN.%>0
GoSub LEVEL:GoSub LEVEL:GoSub LEVEL|
SWITCH$(SWITCH%+1)=COND$|
SWITCH%=SWITCH%+1
else
EBUF$="operand":GoSub ERRORS
endwèendp
proc _CASE
GoSub POP
when KEYWORD%=SWITCH.% AND SWITCH%>0
when C.LN.%>0
XN%=XN%+1:XN.%(XN%)=LEVEL%|
GoSub LEVEL:FLAG%=4|
PBUF$="IF("+SWITCH$(SWITCH%)+"<>"+COND$+") GOTO "|
GoSub OUT_LINE
else
EBUF$="operand":GoSub ERRORS
endw
else
GoSub PUSH|
EBUF$=KEYWORD$(SWITCH.%):GoSub ERRORS
endw
endp
proc _BREAK
GoSub POP
when KEYWORD%=SWITCH.%
F.%=LEVEL%:GoSub POP:T.%=LEVEL%:TK%=T.%|
FLAG%=4:PBUF$="GOTO ":GoSub OUT_LINE|
KEYWORD%=SWITCH.%|
LEVEL%=T.%:GoSub PUSH|
LEVEL%=F.%:GoSub PUSH
else
GoSub PUSH|
EBUF$=KEYWORD$(SWITCH.%):GoSub ERRORS
endw
endp
proc _ENDC
GoSub POP
when KEYWORD%=SWITCH.%
F.%=LEVEL%:GoSub POP:T.%=LEVEL%:GoSub POP|
GoSub POPOFF:SWITCH%=SWITCH%-1
else
GoSub PUSH|
EBUF$=KEYWORD$(SWITCH.%):GoSub ERRORS
endw
endp
proc OUT_LINE
'
' Build and output lines to the temp file.
'
when FLAG%<2 AND C.LN.%=0
EBUF$="condition":GoSub ERRORS
else
NUM%=NUM%+1:OFFSET%=1
IF(FLAG%<2 OR FLAG%>3)THEN LEVEL$=STR$(TK%):MID$(LEVEL$,1,1)="@"
switch FLAG%
case 0
PBUF$="IF("+COND$+") GOTO "+LEVEL$
break
case 1
PBUF$="IF NOT("+COND$+") GOTO "+LEVEL$è break
case 2
GoSub STACK_IT
break
case 4
PBUF$=PBUF$+LEVEL$
endc
PRINT #T.FILE%,RIGHT$(STR$(NUM%),LEN(STR$(NUM%))-1);SKIP$;PBUF$;COMMENT$
IF(XN%>0 AND FLAG%<>2)THEN GoSub STORE_IT
endw
COMMENT$="":PBUF$="":LEVEL$=""
endp
proc STORE_IT
'
' Pop off the target place savers and make tokens of them.
'
OFFSET%=0|
FOR I%=1 TO XN%|
LEVEL$=STR$(XN.%(I%)):MID$(LEVEL$,1,1)="@"|
GoSub STACK_IT|
NEXT I%|
XN%=0
endp
proc STACK_IT
'
' Store the tokens and labels with their corresponding line numbers.
'
STACK.%=STACK.%+1|
STACK%(STACK.%)=NUM%+OFFSET%|
STACK$(STACK.%)=LEVEL$|
IF(COMPIL%)THEN NUM.%(STACK.%)=NUM%+OFFSET%
OFFSET%=0
endp
proc PASS_2
'
' This is the second phase of processing.
' First the stack has to be sorted in ascending order,
' so we can use a binary search on it.
' Then we read the temp file and process it a line at
' a time.
'
GoSub SORT|
OFFSET%=2|
Open"I",T.FILE%,T.FILE$|
Open"O",O.FILE%,O.FILE$
loop
LINE INPUT #T.FILE%,BUF$|
GoSub PROCESS_1
until EOF(T.FILE%)
endp
proc PROCESS_1
'
' Scan the input line a word at a time.
' The first word will be the line number.
' Then write the line to the output file.è '
INDEX%=0:ONFLAG%=0:LN.%=LEN(BUF$)|
GoSub PARSER|
IF(COMPIL%)THEN GoSub COMPIL
while FIRST%<=LEN(BUF$)
unless LEN(TEXT$)>7 OR LEN(TEXT$)<2 OR VAL(TEXT$)>0
GoSub FIND_IT
endu
GoSub PARSER
wend
PRINT #O.FILE%,BUF$
endp
proc COMPIL
'
' Binary search the number stack to see if the line number is used.
'
TEXT%=VAL(TEXT$):HIGH%=STACK.%+1:LOW%=0
unless TEXT%<NUM.%(1) OR TEXT%>NUM.%(STACK.%)
while((HIGH%-LOW%)>1)|
I%=(HIGH%+LOW%)\2
when NUM.%(I%)=TEXT%
TEXT%=-1:LOW%=HIGH%
else when NUM.%(I%)<TEXT%
LOW%=I%
else
HIGH%=I%
endw
wend
endu
IF(TEXT%>0)THEN BUF$=SPACE$(LEN(TEXT$)+1)+COND$
endp
proc FIND_IT
'
' Look for BASIC'S keywords and get the token/label to replace
' with the corresponding line number.
'
C.$=TEXT$:GoSub _Fold
when C.$="on"
ONFLAG%=-1
else when LEN(C.$)>3
unless INSTR(BASIC$,C.$)=0 OR COLN%
GoSub PARSER:I$=LEFT$(TEXT$,1)
unless I$="@" OR LEN(TEXT$)<>4
C.$=TEXT$:GoSub _Fold|
IF(C.$="else")THEN RETURN
endu
unless I$="0" AND ONFLAG%
IF(ONFLAG%)THEN GoSub ON_FLAG ELSE GoSub SEARCH
endu
endu
endw
endp
proc ON_FLAG
'
' Resolve the `ON GOTO' or `ON GoSub' statements. è ' Parse all the way to the end of the input line.
'
OFFSET%=1
while(FIRST%<=LEN(BUF$))
IF(TEXT$<>"")THEN GoSub SEARCH
GoSub PARSER
wend
OFFSET%=2
endp
proc SEARCH
'
' Binary search the token stack to get the corresponding line number.
'
HIGH%=STACK.%+1:LOW%=0:FIND%=-1
while((HIGH%-LOW%)>1)|
I%=(HIGH%+LOW%)\2
when STACK$(I%)=TEXT$
FIND%=STACK%(I%):LOW%=HIGH%
else when STACK$(I%)<TEXT$
LOW%=I%
else
HIGH%=I%
endw
wend
when FIND%>0
GoSub STUFF_IT
else when TEXT$<>""
ERRORS%=ERRORS%+1|
PRINT"MISSING LABEL (";TEXT$;")"
endw
endp
proc STUFF_IT
'
' Replace the token/label with the corresponding line number.
'
NUM$=STR$(FIND%):SP$=""|
L$=LEFT$(BUF$,FIRST%-OFFSET%)
IF(LEFT$(COND$,1)<>" " AND LEFT$(COND$,1)<>":" AND ONFLAG%=0)THEN SP$=" "
BUF$=L$+NUM$+SP$+COND$|
INDEX%=LEN(L$)+LEN(NUM$)|
LN.%=LEN(BUF$)
endp
proc SORT
'
' Shell-Metzner in-memory sort of the token/label stack.
' Sort the line number stack if the compile flag is set.
'
PT.%=STACK.%|
while (PT.%>0)|
PT.%=PT.%\2
when PT.%>0
JT.%=1:KT.%=STACK.%-PT.%|
while (JT.%<=KT.%)|
LT.%=JT.%:CT.%=LT.%+PT.%
while (LT.%>0 AND STACK$(LT.%)>=STACK$(CT.%))è SWAP STACK$(LT.%),STACK$(CT.%)|
SWAP STACK%(LT.%),STACK%(CT.%)
CT.%=LT.%:LT.%=LT.%-PT.%:LT.%=LT.%*(1+(LT.%<0))
wend
when COMPIL%
LT.%=JT.%:CT.%=LT.%+PT.%
while (LT.%>0 AND NUM.%(LT.%)>=NUM.%(CT.%))
SWAP NUM.%(LT.%),NUM.%(CT.%)|
CT.%=LT.%:LT.%=LT.%-PT.%:LT.%=LT.%*(1+(LT.%<0))
wend
endw
JT.%=JT.%+1|
wend
endw
wend
endp
'------------------------------------------------------
'- ** Sub-Routine Division -
'------------------------------------------------------
proc PARSER
C.LN.%=0:I.%=0:COLN%=0:II%=32:TEXT%=0:COND$=""|
TRM$=TM$+CHR$(58*ABS(INDEX%>0))
while(INSTR(TRM$,CHR$(II%))>0)|
INDEX%=INDEX%+1|
IF(INDEX%<=LEN(BUF$))THEN II%=ASC(MID$(BUF$,INDEX%,1)) ELSE II%=7
wend|
FIRST%=INDEX%
while(II%<>32 AND II%<>7)
when INSTR(TRM$,CHR$(II%))>0 AND TEXT%=0
COLN%=(CHR$(II%)=":"):I.%=1:II%=32
else
when II%=34 OR II%=40 OR II%=41
IF(II%=34)THEN INDEX%=INSTR(INDEX%+1,BUF$,CHR$(34))
IF(II%=40)THEN TEXT%=TEXT%+1 ELSE IF(II%=41)THEN TEXT%=TEXT%-1
endw
loop
INDEX%=INDEX%+1|
IF(INDEX%<=LEN(BUF$))THEN II%=ASC(MID$(BUF$,INDEX%,1)) ELSE II%=7
endl unless II%=32 AND TEXT%<>0
endw
wend
TEXT$=MID$(BUF$,FIRST%,INDEX%-FIRST%)|
IF(LEN(BUF$)>INDEX%)THEN COND$=RIGHT$(BUF$,(LEN(BUF$)-INDEX%)+I.%):C.LN.%=LEN(COND$)
endp
proc FILENAMES
LINE INPUT"INPUT FILE [.P]:",I.FILE$
unless I.FILE$=""
COMPIL%=(INSTR(I.FILE$,"/")>0)
IF(COMPIL%)THEN I.FILE$=LEFT$(I.FILE$,LEN(I.FILE$)-1)
IF(INSTR(I.FILE$,DOT$)=0)THEN I.FILE$=I.FILE$+IEXT$
LK.$=I.FILE$:LK.%=I.FILE%:GoSub _Lookup:I.FILE%=LK.%|
GOOD%=(I.FILE%<>FALSE%)
unless GOOD%=FALSE%
I%=INSTR(1,I.FILE$,DOT$)
IF(I%=0)THEN I%=LEN(I.FILE$)+1è E.FILE$=LEFT$(I.FILE$,I%-1)|
LINE INPUT"OUTPUT FILE [.BAS]:",O.FILE$
IF(O.FILE$="")THEN O.FILE$=E.FILE$
IF(INSTR(O.FILE$,DOT$)=0)THEN O.FILE$=O.FILE$+OEXT$
E.FILE$=E.FILE$+EEXT$
endu
endu
endp
proc INCLUDES
GoSub FILES
when FILE.%>0
Open"I",FILE.%,FILE$|
FILE%=FILE.%
else
EBUF$="include "+FILE$:GoSub ERRORS
endw
endp
proc SUBROUTINE
GoSub FILES
when FILE.%>0
TEXT%=0
while(TEXT%<INCS%)
TEXT%=TEXT%+1|
IF(FILE$=INC$(TEXT%))THEN TEXT%=INCS%+1
wend
IF(TEXT%=INCS%)THEN INCS%=INCS%+1:INC$(INCS%)=FILE$
else
EBUF$="include "+FILE$:GoSub ERRORS
endw
endp
proc FILES
FILE$=RIGHT$(TEXT$,LEN(TEXT$)-1)|
IF(INSTR(FILE$,DOT$)=0)THEN FILE$=FILE$+INCL$
FILE.%=FILE%+1|
LK.$=FILE$:LK.%=FILE.%:GoSub _Lookup:FILE.%=LK.%
endp
proc ERRORS
ERRORS%=ERRORS%+1|
EBUF$="ERR#"+STR$(ERRORS%)+" MISSING ("+EBUF$+") PROC <"+LPROC$+">"|
EBUF$=EBUF$+" AT"+STR$(KERR%)|
PRINT EBUF$:PRINT #E.FILE%,EBUF$
endp
proc _Fold
f.0%=1
while(f.0%<=LEN(C.$))
f.2%=ASC(MID$(C.$,f.0%,1))
f.2%=f.2%+(32*ABS(f.2%>64 AND f.2%<91))
MID$(C.$,f.0%,1)=CHR$(f.2%):f.0%=f.0%+1
wend
endp
proc _Lookup
OPEN"R",LK.%,LK.$:L.K!=LOF(LK.%):CLOSE LK.%
IF(L.K!<1)THEN LK.%=0:KILL LK.$
endp
è
XFRAME.M
'┌────────────────────────────────────────────────────┐
'│ UTL: IBM & MSDOS ONLY │
'└────────────────────────────────────────────────────┘
'- Program:XFRAME
'- System :PPE TOOLS
'- Module :UTL
'- Task :INSERT FRAMES IN TEXT FILES
'- :EXAMPLE SOURCE TO BE PREPROCESSED BY BMLP & BSLP
'- Created:10.1.84
'- By :D. L. Bendorf
'- Version:N/A
'- Notes :This is a simple little program utility to insert pretty
'- :block graphic frames (like those above and below) in text files.
'- :Four types of frames are provided.
'- :To insert a frame, you will have to mark the location.
'- :This is done by using a `^' carrot for the upper left and right
'- :corners and then bottom left corner.
'- :Insert a number (0..3) on the right side of the upper left corner
'- :to select the type of frame you want; the default is zero.
'- :Examples:
'- : 1. ^0 ^ ╔═════╗
'- : will make ║ ║
'- : ^ ╚═════╝
'- :
'- : 2. ^1 ^ ┌─────┐
'- : will make │ │
'- : ^ └─────┘
'- :
'- : 3. ^2 ^ ╓─────╖
'- : will make ║ ║
'- : ^ ╙─────╜
'- :
'- : 4. ^3 ^ ╒═════╕
'- : will make │ │
'- : ^ ╘═════╛
'- :If you need to change then corner-stone (^) to something else,
'- :use: ^=some-other-mark ,example: ^=@
'- :Tabs are set to expand to four spaces, to set to some other value,
'- :use: ^Tsome-value , example: ^T8 sets tabs to expand eight spaces.
'-
'- History:
'┌────────────────────────────────────────────────────┐
'│ ** Data Division │
'└────────────────────────────────────────────────────┘
LIBRARY XFRAME
NULL$ = ""
DOT$ = "."
BLANK$ = " "
I.FILE%=1
O.FILE%=2èI.FILE$=""
O.FILE$=""
XLINE.$=" "
FALSE% =0
GOOD% =0
MK$ =CHR$(94)
TB% =4
EQUATE$="="
TABS$ ="T"
IEXT$ =".DOC"
OEXT$ =".F"
macro INSERT
BK%=[1]:CK%=[2]:GoSub INSERT-BLOCK
endm
macro FSPEC
I%=INSTR(1,[1],DOT$):IF(I%=0)THEN [1]=[1]+[2]
endm
DIM TLC%(3),TRC%(3),HL%(3),BLC%(3),BRC%(3),VL%(3)
DIM EL%(20)
DIM BL%(20)
DIM MK%(132,20)
READ TLC%(0),TLC%(1),TLC%(2),TLC%(3)
READ TRC%(0),TRC%(1),TRC%(2),TRC%(3)
READ HL%(0),HL%(1),HL%(2),HL%(3)
READ BLC%(0),BLC%(1),BLC%(2),BLC%(3)
READ BRC%(0),BRC%(1),BRC%(2),BRC%(3)
READ VL%(0),VL%(1),VL%(2),VL%(3)
DATA 201,218,214,213
DATA 187,191,183,184
DATA 205,196,196,205
DATA 200,192,211,212
DATA 188,217,189,190
DATA 186,179,186,179
for I%=0 to 20
for Q%=0 to 132
MK%(Q%,I%)=-1
next Q%
next I%
'┌────────────────────────────────────────────────────┐
'│ ** Procedure Division │
'└────────────────────────────────────────────────────┘
prog XFRAME
GoSub FILENAMES
when GOOD%
GoSub PROCESS-FILE
PRINT"Done!"
else unless I.FILE$=NULL$
PRINT"Can not open ";I.FILE$
endw
pendèproc FILENAMES
line input"INPUT FILE:",I.FILE$
unless I.FILE$=NULL$
$fspec I.FILE$,IEXT$
$lookup I.FILE$,I.FILE%
GOOD%=(I.FILE% <> FALSE%)
unless GOOD%=FALSE%
line input"OUTPUT FILE:",O.FILE$
unless O.FILE$<>NULL$
I%=INSTR(1,I.FILE$,DOT$)
IF(I%=0)THEN I%=LEN(I.FILE$)+1
O.FILE$=LEFT$(I.FILE$,I%-1)
endu
$fspec O.FILE$,OEXT$
OPEN"O",O.FILE%,O.FILE$
OPEN"I",I.FILE%,I.FILE$
PRINT"Writing..";O.FILE$
endu
endu
endp
proc PROCESS-FILE
loop
$linput I.FILE%,XLINE.$
when INSTR(1,XLINE.$,MK$)>0
GoSub PROCESS-XLINE
else when BQ%>0
GoSub INSERT-SIDES
endw
unless XLINE.$=BLANK$
PRINT #O.FILE%,XLINE.$
endu
until EOF(I.FILE%)
CLOSE
endp
proc PROCESS-XLINE
GoSub REMOVE-TABS
DQ%=BQ%
I%=0
while INSTR(I%+1,XLINE.$,MK$)>0
GoSub SCAN-XLINE
when IZ%=0
IF(DQ%>0)THEN GoSub INSERT-SIDES
GoSub TOP-FRAME
else
GoSub BOTTOM-FRAME
endw
wendè IF(BQ%>0)THEN GoSub INSERT-SIDES
endp
proc SCAN-XLINE
I%=INSTR(I%+1,XLINE.$,MK$):IK%=0:IZ%=0
while IK%<DQ% and IZ%=0
IF(MK%(I%,IK%)>-1)THEN IZ%=1 ELSE IK%=IK%+1
wend
endp
proc TOP-FRAME
BL%(BQ%)=I%
EL%(BQ%)=INSTR(I%+1,XLINE.$,MK$)
when EL%(BQ%)>0
FT%=VAL(MID$(XLINE.$,I%+1,1))
MID$(XLINE.$,I%+1,1)=" "
IF(EL%(BQ%)>EK%)THEN EK%=EL%(BQ%)
MK%(BL%(BQ%),BQ%)=FT%
Q%=BQ%:GoSub TOP-LINE
BQ%=BQ%+1:DQ%=BQ%
else when MID$(XLINE.$,I%+1,1)=EQUATE$
MK$=MID$(XLINE.$,I%+2,1):XLINE.$=BLANK$
else when MID$(XLINE.$,I%+1,1)=TABS$
TB%=val(MID$(XLINE.$,I%+2,1)):XLINE.$=BLANK$
endw
endp
proc BOTTOM-FRAME
Q%=IK%:FT%=MK%(I%,IK%)
GoSub BOTTOM-LINE
MK%(I%,IK%)=-1:BQ%=BQ%-1
endp
proc TOP-LINE
GoSub LINE-LENGTH
B%=BL%(Q%):E%=EL%(Q%)
$insert B%,TLC%(FT%)
GoSub TOPS-BOTTOMS
$insert E%,TRC%(FT%)
endp
proc BOTTOM-LINE
GoSub LINE-LENGTH
B%=BL%(Q%):E%=EL%(Q%)
$insert B%,BLC%(FT%)
GoSub TOPS-BOTTOMS
$insert E%,BRC%(FT%)
endp
proc TOPS-BOTTOMS
B%=B%+1
while B%<E%
$insert B%,HL%(FT%)
B%=B%+1
wend
endp
proc INSERT-SIDES
IF(INSTR(XLINE.$,CHR$(9)))THEN GoSub REMOVE-TABS
GoSub LINE-LENGTH
J%=0
while J%<BQ%è FT%=MK%(BL%(J%),J%)
when FT%>-1
$insert BL%(J%),VL%(FT%)
$insert EL%(J%),VL%(FT%)
endw
J%=J%+1
wend
endp
proc LINE-LENGTH
unless LEN(XLINE.$)=>EK%
XLINE.$=XLINE.$+STRING$(EK%-LEN(XLINE.$)+1,32)
endu
endp
proc REMOVE-TABS
T%=INSTR(1,XLINE.$,CHR$(9))
while T%>0
L$=LEFT$(XLINE.$,T%-1)
R$=RIGHT$(XLINE.$,LEN(XLINE.$)-T%)
XLINE.$=L$+STRING$(TB%,32)+R$
T%=INSTR(1,XLINE.$,CHR$(9))
wend
endp
proc INSERT-BLOCK
unless BK%=0
when MID$(XLINE.$,BK%,1)=" " or MID$(XLINE.$,BK%,1)=MK$
MID$(XLINE.$,BK%,1)=CHR$(CK%)
endw
endu
endp
'┌────────────────────────────────────────────────────┐
'│ ** Sub-Routine Division │
'└────────────────────────────────────────────────────┘
XFRAME.ML
;;==========================================================================
; NOTE:
; THE `|' VERTICAL BAR IS USED AS A CONTINUATION MARK.
; DOCUMENTATION ABREVIATIONS:
; S/L = STRING VARIABLE OR LITERAL ENCLOSED WITH DOUBLE QUOTES.
; N/L = NUMERIC VARIABLE OR LITERAL.
; S = STRING VARIABLE ONLY.
; N = NUMERIC VARIABLE ONLY.
; S/N = STRING OR NUMERIC VARIABLE.
;
;;==========================================================================
;**
::LOOKUP (Macro)
;** FUNCTION:
;** Verify the existence of a file.
;** USAGE:
;** Two parameters required.
;** Calling:
;** [1] - S/L - a valid file name.è;** [2] - N - a valid file number (>0).
;** Returning:
;** [2] - zero if file not found.
;** EXAMPLE:
;** TXT% = 2
;** $lookup "myfile.txt",TXT%
;** (if "myfile.txt" is not found then TXT% = 0.)
;** $lookup MYFILE$,TXT%
;**
MACRO LOOKUP
XX.$=[1]:XX.%=[2]:Gosub _Lookup:[2]=XX.%
$$_LOOKUP
ENDM
;;==========================================================================
;**
::_LOOKUP (Subroutine)
;** FUNCTION:
;** Subroutine called by LOOKUP macro.
;**
MACRO _LOOKUP
Proc _Lookup
Open"R",XX.%,XX.$:X.X!=LOF(XX.%):Close XX.%|
IF(X.X!<1)Then XX.%=0:Kill XX.$
Endp
ENDM
;;==========================================================================
;**
::OPENFI (Macro)
;** FUNCTION:
;** Open a file for input.
;** USAGE:
;** Two parameters required.
;** Calling:
;** [1] - S/L - valid file name.
;** [2] - N/L - valid file number.
;** EXAMPLE:
;** $openfi "myfile.txt",2
;** $openfi MYFILE$,MYFILE%
;**
MACRO OPENFI
Open"I",[2],[1]
ENDM
;;==========================================================================
;**
::OPENFO (Macro)
;** FUNCTION:
;** Open a file for output.
;** USAGE:
;** Two parameters required.
;** Calling:
;** [1] - S/L - valid file name.
;** [2] - N/L - valid file number.
;** EXAMPLE:
;** $openfo "myfile.txt",2
;** $openfo MYFILE$,MYFILE%è;**
MACRO OPENFO
Open"O",[2],[1]
ENDM
;;==========================================================================
;**
::LINPUT (Macro)
;** FUNCTION:
;** Input a line from a file open for input.
;** USAGE:
;** Two parameters required.
;** Calling:
;** [1] - N/L - valid file number.
;** Returning:
;** [2] - S - string buffer.
;** EXAMPLE:
;** $linput 2,BUFFER$
;** $linput BUF%,BUFFER$
;**
MACRO LINPUT
Line Input #[1],[2]
ENDM
;;==========================================================================